package edu.northwestern.cbits.purple.notifier;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.IntentService;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.OrientationEventListener;
public class WidgetIntentService extends IntentService
{
public final static String WIDGET_ACTION = "edu.northwestern.cbits.purple.WIDGET_ACTION";
public final static String UPDATE_WIDGET = "edu.northwestern.cbits.purple.UPDATE_WIDGET";
public final static String UPDATE_WIDGETS = "edu.northwestern.cbits.purple.UPDATE_WIDGETS";
public static final String ACTION_BOOT = "edu.northwestern.cbits.purple.ACTION_BOOT";
public final static String WIDGET = "WIDGET";
public final static String LAUNCH_INTENT = "LAUNCH_INTENT";
private static OrientationEventListener _orientation = null;
private int _lastOrientation = 0;
public WidgetIntentService()
{
super("WidgetIntentService");
}
public WidgetIntentService(String name)
{
super(name);
}
protected void onHandleIntent(Intent intent)
{
final WidgetIntentService me = this;
if (WidgetIntentService._orientation == null)
{
WidgetIntentService._orientation = new OrientationEventListener(this)
{
public void onOrientationChanged(int orientation)
{
if (Math.abs(orientation - me._lastOrientation) > 45)
{
Intent newIntent = new Intent(WidgetIntentService.UPDATE_WIDGETS);
me.startService(newIntent);
me._lastOrientation = orientation;
}
}
};
}
if (intent.hasExtra("identifier"))
{
String identifier = intent.getStringExtra("identifier");
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String key = identifier + "_saved_state";
String idString = prefs.getString(key, "{}");
try
{
JSONObject json = new JSONObject(idString);
for (String bundleKey : intent.getExtras().keySet())
{
if (AppWidgetManager.EXTRA_APPWIDGET_ID.equals(bundleKey) == false)
{
String value = intent.getStringExtra(bundleKey);
json.put(bundleKey, value);
}
}
@SuppressWarnings("unchecked")
Iterator<String> iter = json.keys();
while (iter.hasNext())
{
String jsonKey = iter.next();
String value = json.getString(jsonKey);
if (intent.hasExtra(jsonKey) == false)
intent.putExtra(jsonKey, value);
}
Editor e = prefs.edit();
e.putString(key, json.toString());
e.commit();
}
catch (JSONException e)
{
e.printStackTrace();
}
}
if (ACTION_BOOT.equals(intent.getAction()))
{
String[] identifiers = IdentifiersManager.fetchIdentifiers(this);
for (String identifier : identifiers)
{
Bundle b = this.fetchWidgetState(identifier);
Intent update = new Intent(WidgetIntentService.UPDATE_WIDGETS);
update.putExtras(b);
this.onHandleIntent(update);
}
}
else if (UPDATE_WIDGETS.equals(intent.getAction()))
{
String identifier = intent.getStringExtra("identifier");
int[] widgetIds = this.getWidgetIds(identifier);
for (int widgetId : widgetIds)
{
this.refreshWidget(widgetId, intent);
}
this.saveWidgetState(identifier, intent.getExtras());
}
else if (UPDATE_WIDGET.equals(intent.getAction()))
{
String identifier = intent.getStringExtra("identifier");
int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, Integer.MAX_VALUE);
this.registerIdentifier(identifier, widgetId);
this.saveWidgetState(identifier, intent.getExtras());
int[] widgetIds = this.getWidgetIds(identifier);
for (int id : widgetIds)
{
this.refreshWidget(id, intent);
}
}
}
@SuppressWarnings("unchecked")
private Bundle fetchWidgetState(String identifier)
{
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String jsonString = prefs.getString("widget_state_" + identifier, "{}");
Bundle bundle = new Bundle();
try
{
JSONObject json = new JSONObject(jsonString);
Iterator<String> keys = json.keys();
while (keys.hasNext())
{
String key = keys.next();
bundle.putString(key, json.getString(key));
}
}
catch (JSONException e)
{
e.printStackTrace();
}
return bundle;
}
private void saveWidgetState(String identifier, Bundle extras)
{
JSONObject json = new JSONObject();
for (String key : extras.keySet())
{
try
{
json.put(key, extras.get(key).toString());
}
catch (JSONException e)
{
e.printStackTrace();
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
Editor e = prefs.edit();
e.putString("widget_state_" + identifier, json.toString());
e.commit();
}
}
private void refreshWidget(int widgetId, Intent intent)
{
String widget = this.fetchType(widgetId);
if (widget == null)
{
this.unregisterIdentifier(widgetId);
return;
}
if (BasicWidgetProvider.NAME.equals(widget))
BasicWidgetProvider.setupWidget(this, widgetId, intent);
else if (TextWidgetProvider.NAME.equals(widget))
TextWidgetProvider.setupWidget(this, widgetId, intent);
else if (TitleWidgetProvider.NAME.equals(widget))
TitleWidgetProvider.setupWidget(this, widgetId, intent);
else if (ImageWidgetProvider.NAME.equals(widget))
ImageWidgetProvider.setupWidget(this, widgetId, intent);
else if (FourWidgetProvider.NAME.equals(widget))
FourWidgetProvider.setupWidget(this, widgetId, intent);
else if (FiveWidgetProvider.NAME.equals(widget))
FiveWidgetProvider.setupWidget(this, widgetId, intent);
else if (BadgeWidgetProvider.NAME.equals(widget))
BadgeWidgetProvider.setupWidget(this, widgetId, intent);
else if (SmallBadgeWidgetProvider.NAME.equals(widget))
SmallBadgeWidgetProvider.setupWidget(this, widgetId, intent);
}
private int[] getWidgetIds(String identifier)
{
String key = "widget_identifiers_" + identifier;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String idList = prefs.getString(key, "");
ArrayList<String> identifiers = new ArrayList<String>();
String[] tokens = idList.split(";");
for (int i = 0; i < tokens.length; i++)
{
String id = tokens[i].trim();
if (id.length() > 0)
identifiers.add(id);
}
int[] intIds = new int[identifiers.size()];
for (int i = 0; i < identifiers.size(); i++)
{
intIds[i] = Integer.parseInt(identifiers.get(i));
}
return intIds;
}
private void registerIdentifier(String identifier, int widgetId)
{
this.unregisterIdentifier(widgetId);
String key = "widget_identifiers_" + identifier;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String idList = prefs.getString(key, "");
ArrayList<String> identifiers = new ArrayList<String>();
String[] tokens = idList.split(";");
for (int i = 0; i < tokens.length; i++)
{
String id = tokens[i].trim();
if (id.length() > 0)
identifiers.add(id);
}
String stringId = "" + widgetId;
if (identifiers.contains(stringId) == false)
identifiers.add(stringId);
StringBuilder sb = new StringBuilder();
for (String id : identifiers)
{
if (sb.length() > 0)
sb.append(";");
sb.append(id);
}
Editor e = prefs.edit();
e.putString(key, sb.toString());
e.commit();
}
private void unregisterIdentifier(int widgetId)
{
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
Map<String, ?> values = prefs.getAll();
for (String key : values.keySet())
{
if (key.startsWith("widget_identifiers_"))
{
String identifier = key.replaceAll("widget_identifiers_", "");
this.unregisterIdentifier(identifier, widgetId);
}
}
}
private String fetchType(int widgetId)
{
ArrayList<ComponentName> names = new ArrayList<ComponentName>();
names.add(new ComponentName(this, BasicWidgetProvider.class));
names.add(new ComponentName(this, TextWidgetProvider.class));
names.add(new ComponentName(this, ImageWidgetProvider.class));
names.add(new ComponentName(this, TitleWidgetProvider.class));
names.add(new ComponentName(this, FourWidgetProvider.class));
names.add(new ComponentName(this, FiveWidgetProvider.class));
names.add(new ComponentName(this, BadgeWidgetProvider.class));
names.add(new ComponentName(this, SmallBadgeWidgetProvider.class));
AppWidgetManager widgets = AppWidgetManager.getInstance(this);
for (ComponentName name : names)
{
int[] widgetIds = widgets.getAppWidgetIds(name);
for (int arrayId : widgetIds)
{
if (widgetId == arrayId)
{
if (".BasicWidgetProvider".equals(name.getShortClassName()))
return BasicWidgetProvider.NAME;
else if (".TextWidgetProvider".equals(name.getShortClassName()))
return TextWidgetProvider.NAME;
else if (".ImageWidgetProvider".equals(name.getShortClassName()))
return ImageWidgetProvider.NAME;
else if (".TitleWidgetProvider".equals(name.getShortClassName()))
return TitleWidgetProvider.NAME;
else if (".FourWidgetProvider".equals(name.getShortClassName()))
return FourWidgetProvider.NAME;
else if (".FiveWidgetProvider".equals(name.getShortClassName()))
return FiveWidgetProvider.NAME;
else if (".BadgeWidgetProvider".equals(name.getShortClassName()))
return BadgeWidgetProvider.NAME;
else if (".SmallBadgeWidgetProvider".equals(name.getShortClassName()))
return SmallBadgeWidgetProvider.NAME;
}
}
}
return null;
}
private void unregisterIdentifier(String identifier, int widgetId)
{
String key = "widget_identifiers_" + identifier;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
int[] widgetIds = this.getWidgetIds(identifier);
ArrayList<Integer> savedIds = new ArrayList<Integer>();
for (int savedId : widgetIds)
{
if (savedId != widgetId)
savedIds.add(Integer.valueOf(savedId));
}
if (savedIds.size() == widgetIds.length)
return;
StringBuilder sb = new StringBuilder();
for (Integer id : savedIds)
{
if (sb.length() > 0)
sb.append(";");
sb.append(id);
}
Editor e = prefs.edit();
e.putString(key, sb.toString());
e.commit();
}
}